import time
import os
import sqlite3 as sql

import cv2
from ninja import Router, Query
from ninja.responses import Response
from django.http import StreamingHttpResponse

from .schema import ActionListSchemaIn, ServoListSchemeIn, ActionGroupSchemaIn, HandleControlSchemaIn

from hiwonder import Board

router = Router()


@router.post('/action/run/', summary='运行一组动作')
def runActionList(request, data: ActionListSchemaIn):
    """
    接收一串动作，运行动作中的每个舵机
    """
    for action in data.action_lst:
        servo_id, pulse, use_time = action.servo_id, action.pulse, action.use_time
        Board.setBusServoPulse(servo_id, pulse, use_time)

    # 延时后返回，延时时间为舵机的运行时间
    max_use_time = max([i.use_time for i in data.action_lst])
    time.sleep(max_use_time/1000)

    res_data = {'message': '运行成功'}
    return res_data


@router.post('/action_group/run/', summary='运行一个动作组文件')
def runActionGroup(request, data: ActionGroupSchemaIn):
    """
    接收数据，读取相应的动作组文件并运行
    """
    file_path = f'/home/pi/TonyPi/ActionGroups/{data.file_name}.d6a'
    if not os.path.exists(file_path):
        return Response({'message': '未能找到该动作组文件'}, status=400)

    ag = sql.connect(file_path)
    cu = ag.cursor()
    cu.execute("select * from ActionGroup")
    while True:
        act = cu.fetchone()
        if not act:
            break
        for i in range(0, len(act) - 2, 1):
            Board.setBusServoPulse(i + 1, act[2 + i], act[1])
        time.sleep(float(act[1]) / 1000.0)
    cu.close()
    ag.close()

    res_data = {'message': '运行成功'}
    return res_data


@router.post('/servo/unload/', summary='舵机掉电')
def unloadServoList(request, data: ServoListSchemeIn):
    """
    接收舵机id数组，对该数组的舵机进行断电
    """
    for servo_id in data.servo_lst:
        Board.unloadBusServo(servo_id)
    res_data = {'message': '掉电成功'}
    return res_data


@router.get('/camera/', summary='获取摄像头视频')
def viewCamera(request):
    """
    返回摄像头视频流
    """
    def gen_display(camera):
        while True:
            ret, frame = camera.read()
            if ret:
                ret1, frame = cv2.imencode('.jpeg', frame)
                if ret1:
                    yield (b'--frame\r\n'
                           b'Content-Type: image/jpeg\r\n\r\n' + frame.tobytes() + b'\r\n')

    # rtsp_url = 'http://127.0.0.1:8080/?action=stream?dummy=param.mjpg'
    rtsp_url = -1
    camera = cv2.VideoCapture(rtsp_url)
    if not camera.isOpened():
        return Response({'message': '无法连接到摄像头'}, status=400)
    return StreamingHttpResponse(gen_display(camera), content_type='multipart/x-mixed-replace; boundary=frame')


@router.post('/handle_control/', summary='运行一个动作组文件')
def handleControl(request, data: HandleControlSchemaIn):
    """
    手柄控制，支持前进，后退，左右转，AYXB键
    """
    action_dict = {
        'go': 'go_forward_fast',             # 前进
        'back': 'back',         # 后退
        'left': 'left',             # 左转
        'right': 'right',           # 右转
        'A': 'stand',           # A键-正站立
        'Y': 'squat',           # Y键-蹲下
        'X': 'sit_ups',         # X键-仰卧起坐
        'B': 'bow',               # B键-鞠躬
    }   # 动作字典，将动作映射成对应的动作组文件
    file_name = action_dict.get(data.action, None)
    if not file_name:
        return Response({'message': '未能找到该动作对应的执行指令'}, status=400)
    file_path = f'/home/pi/TonyPi/ActionGroups/{file_name}.d6a'
    if not os.path.exists(file_path):
        return Response({'message': '未能找到该动作对应的执行文件'}, status=400)

    ag = sql.connect(file_path)
    cu = ag.cursor()
    cu.execute("select * from ActionGroup")
    while True:
        act = cu.fetchone()
        if not act:
            break
        for i in range(0, len(act) - 2, 1):
            Board.setBusServoPulse(i + 1, act[2 + i], act[1])
        time.sleep(float(act[1]) / 1000.0)
    cu.close()
    ag.close()

    res_data = {'message': '运行成功'}
    return res_data
